﻿using LxBasic;

namespace LxCore
{
    /// <summary>
    /// 与FvFace基本相同，这是边界处的Face
    /// 取消了NSideCell和gOwner两个参数
    /// </summary>
    public struct FvBouFace
    {
        public FvBouFace(int[] nodes, int c0, bool isRightHand)
        {
            Nodes = new int[nodes.Length];
            Array.Copy(nodes, Nodes, nodes.Length);
            this.OSideCell = c0;
            this.Center = new Vector3d();
            this.Normal = new Vector3d();
            this.Area = 0;
            this.OToN = new Vector3d();
            this.OToNLength = 0;
            this.gDiff = 0;
            this.gT = 0;
            this.FaceNOrth = new();
            if (!isRightHand)
            {
                Array.Reverse(this.Nodes);
            }
        }
        public int OSideCell;
        public double Area;
        public double OToNLength;
        public double gDiff;
        public double gT;//计算非正交修正时用到
        public int[] Nodes;
        public Vector3d Center;
        public Vector3d Normal;//lenth为面的面积
        public Vector3d OToN;//由OwnerCell中心指向NeighborCell中心的矢量
        public Vector3d FaceNOrth;// Normal - gT * OToN,简化计算

        public void CalGeometryInFace(Vector3d[] points)
        {
            FaceGeomCalc fg = new FaceGeomCalc();
            for (int i1 = 2; i1 < Nodes.Length; i1++)
            {
                fg.AddTriangle(points[Nodes[0]], points[Nodes[i1 - 1]], points[Nodes[i1]]);
            }
            (Normal, Center) = fg.GetResult();
            Area = Normal.Length();
        }
        public void CalGeometryAcrossBouFace(FvInnCell[] cells)
        {
            OToN = Center - cells[OSideCell].Center;
            OToNLength = OToN.Length();
            double normalDotOToN = Vector3d.DotProduct(Normal, OToN);
            this.gDiff = Normal.LengthSquared() / normalDotOToN;
            this.gT = normalDotOToN / OToN.LengthSquared();
            this.FaceNOrth = Normal - gT * OToN;
        }
        private Vector3d calCFCorrectPart(in Vector3d aveGrad, double phiN_phiO)////使用C、F点的值对代数平均梯度修正，这是修正部分
        {
            return (phiN_phiO - Vector3d.DotProduct(aveGrad, OToN)) / (OToNLength * OToNLength) * OToN;
        }
        public Vector3d CalCFCorrectedGradientOfBound(Vector3d[] gradPhi, double[] xInn, double xBou)
        {
            Vector3d aveGrad = gradPhi[OSideCell];
            return aveGrad + calCFCorrectPart(aveGrad, xBou - xInn[OSideCell]);
        }
        public Vector3d CalCFGradCorrectionOfBound(Vector3d[] gradPhi, double[] xInn, double xBou)
        {
            Vector3d aveGrad = gradPhi[OSideCell];
            return calCFCorrectPart(aveGrad, xBou - xInn[OSideCell]);
        }
        public double CalNonOrthogonalityCorrectionOfBound(Vector3d[] gradPhi, double[] xInn, double xBou)
        {
            return Vector3d.DotProduct(gradPhi[OSideCell], FaceNOrth) + (xBou - xInn[OSideCell]) * (gT - gDiff);
        }
   
    }
}